package org.fastsyncer.core.util;

import java.util.List;
import java.util.Map;

import javax.naming.NamingException;

import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.entity.DatabaseConfig;
import org.fastsyncer.common.entity.LdapConfig;
import org.fastsyncer.common.entity.Mapping;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.common.entity.RedisConfig;
import org.fastsyncer.common.entity.WebServiceConfig;
import org.fastsyncer.connector.framework.Database;
import org.fastsyncer.connector.ldap.LdapConnector;
import org.fastsyncer.connector.mysql.MysqlConnector;
import org.fastsyncer.connector.oracle.OracleConnector;
import org.fastsyncer.connector.redis.RedisConnector;
import org.fastsyncer.connector.sqlserver.SqlServerConnector;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.AuthenticationException;
import org.springframework.ldap.CommunicationException;

public abstract class ParseDriverTarget extends ParseDriverCommon {

    private static Logger logger = LoggerFactory.getLogger(ParseDriverTarget.class);

    /**
     * 解析目标源
     * 
     * @Title: parseDriverTarget
     * @Description: 解析目标源
     * @param rel
     * @param mappingTask
     * @return: void
     * @throws JSONException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws NamingException 
     * @throws CommunicationException 
     * @throws AuthenticationException 
     */
    protected static void parse(JSONObject rel, MappingTask mappingTask) throws JSONException, InstantiationException, IllegalAccessException, ClassNotFoundException, AuthenticationException, CommunicationException, NamingException {
        // 解析目标源
        JSONObject targetMapping = rel.getJSONObject("targetMapping");
        switch (targetMapping.getString("connector")) {
        case ConnectorConstant.MYSQL_CONNECTOR:
            parseMysqlConnector(mappingTask, targetMapping);
            break;
        case ConnectorConstant.ORACLE_CONNECTOR:
            parseOracleConnector(mappingTask, targetMapping);
            break;
        case ConnectorConstant.SQLSERVER_CONNECTOR:
            parseSqlServerConnector(mappingTask, targetMapping);
            break;
        case ConnectorConstant.WS_CONNECTOR:
            parseWebServiceConnector(mappingTask, targetMapping);
            break;
        case ConnectorConstant.LDAP_CONNECTOR:
            parseLdapConnector(mappingTask, targetMapping);
            break;
        case ConnectorConstant.REDIS_CONNECTOR:
            parseRedisConnector(mappingTask, targetMapping);
            break;
        default:
            break;
        }
    }

    // 解析Redis
    private static void parseRedisConnector(MappingTask mappingTask, JSONObject mappingObj) throws JSONException {
        // 1.获取数据源配置
        RedisConfig config = getRedis(mappingObj.getJSONObject("config"));

        // 2.检查配置是否可用
        boolean alive = RedisConnector.getInstance().isAlive(config);
        if(!alive){
            String err = new StringBuilder("Can't connect ").append(config.getUrl()).toString();
            throw new IllegalArgumentException(err);
        }
        
        // 3.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> fileds = parseFields(mappingObj.getJSONArray("fileds"));

        // 4.设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(mappingObj.getString("name"), config, ConnectorConstant.REDIS_CONNECTOR, fileds, 0);
        mappingTask.setTargetMapping(mapping);
    }

    // 解析Ldap
    private static void parseLdapConnector(MappingTask mappingTask, JSONObject targetMappingObj) throws JSONException, AuthenticationException, CommunicationException, NamingException {
        // 1.获取数据源配置
        LdapConfig targetLdapConfig = getLdap(targetMappingObj.getJSONObject("config"));
        // 检查连接配置是否正确
        LdapConnector.getInstance().getLdapTemplate(targetLdapConfig);

        // 2.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> targetLdapFileds = parseFields(targetMappingObj.getJSONArray("fileds"));

        // 3.设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(targetMappingObj.getString("name"), targetLdapConfig, ConnectorConstant.LDAP_CONNECTOR, targetLdapFileds, 0);
        mappingTask.setTargetMapping(mapping);
    }

    // 解析WebService
    private static void parseWebServiceConnector(MappingTask mappingTask, JSONObject targetMappingObj) throws JSONException {
        // 1.获取数据源配置
        WebServiceConfig targetWSConfig = getWebService(targetMappingObj.getJSONObject("config"));

        // 2.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> targetXmlFileds = parseFields(targetMappingObj.getJSONArray("fileds"));

        // 3.设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(targetMappingObj.getString("name"), targetWSConfig, ConnectorConstant.WS_CONNECTOR, targetXmlFileds, 0);
        mappingTask.setTargetMapping(mapping);
    }

    // 解析SqlServer
    private static void parseSqlServerConnector(MappingTask mappingTask, JSONObject mappingObj) throws JSONException {
        // 1.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> fileds = parseFields(mappingObj.getJSONArray("fileds"));

        // 2.获取数据源配置
        DatabaseConfig config = getDataSource(mappingObj.getJSONObject("config"));

        // 3.获取连接器
        SqlServerConnector connector = SqlServerConnector.getInstance();
        Integer rowCount = connector.getBaseInfoConnector(config).getRowCount();

        // 设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(mappingObj.getString("name"), config, ConnectorConstant.SQLSERVER_CONNECTOR, fileds, rowCount);

        // 4.拼接数据源执行命令
        String targetExecuteCommond = null;
        if (fileds != null && !fileds.isEmpty()) {
            // 4.1解析插入语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_INSERT, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_INSERT, targetExecuteCommond);
            logger.info("targetExecuteInsertCommond:" + targetExecuteCommond);

            // 4.2解析修改语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_UPDATE, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_UPDATE, targetExecuteCommond);
            logger.info("targetExecuteUpdateCommond:" + targetExecuteCommond);

            // 4.3解析删除语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_DELETE, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_DELETE, targetExecuteCommond);
            logger.info("targetExecuteDeleteCommond:" + targetExecuteCommond);
        }
        mappingTask.setTargetMapping(mapping);
    }

    // 解析mysql数据库
    private static void parseMysqlConnector(MappingTask mappingTask, JSONObject mappingObj) throws JSONException {
        // 1.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> fileds = parseFields(mappingObj.getJSONArray("fileds"));

        // 2.获取数据源配置
        DatabaseConfig config = getDataSource(mappingObj.getJSONObject("config"));

        // 3.获取数据量
        Database connector = MysqlConnector.getInstance();
        Integer rowCount = connector.getBaseInfoConnector(config).getRowCount();

        // 4.设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(mappingObj.getString("name"), config, ConnectorConstant.MYSQL_CONNECTOR, fileds, rowCount);

        // 5.拼接数据源执行命令
        parseTargetDBExecuteCommond(fileds, mapping, config, connector);
        
        // 6.保存映射配置
        mappingTask.setTargetMapping(mapping);
    }
    
    // 解析oracle数据库
    private static void parseOracleConnector(MappingTask mappingTask, JSONObject mappingObj) throws JSONException {
        // 1.获取同步数据源、目标源字段和数据源、目标源字段类型
        List<Map<String, Object>> fileds = parseFields(mappingObj.getJSONArray("fileds"));

        // 2.获取数据源配置
        DatabaseConfig config = getDataSource(mappingObj.getJSONObject("config"));

        // 3.获取数据量
        Database connector = OracleConnector.getInstance();
        Integer rowCount = connector.getBaseInfoConnector(config).getRowCount();

        // 设置数据源配置、驱动类型、同步属性、数据量
        Mapping mapping = new Mapping(mappingObj.getString("name"), config, ConnectorConstant.ORACLE_CONNECTOR, fileds, rowCount);

        // 4.拼接数据源执行命令
        String targetExecuteCommond = null;
        if (fileds != null && !fileds.isEmpty()) {
            // 4.1解析插入语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_INSERT, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_INSERT, targetExecuteCommond);
            logger.info("targetExecuteInsertCommond:" + targetExecuteCommond);

            // 4.2解析修改语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_UPDATE, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_UPDATE, targetExecuteCommond);
            logger.info("targetExecuteUpdateCommond:" + targetExecuteCommond);

            // 4.3解析删除语句
            targetExecuteCommond = connector.getJdbcSQL(ConnectorConstant.OPERTION_DELETE, config, fileds, null);
            mapping.getExecuteCommond().put(ConnectorConstant.OPERTION_DELETE, targetExecuteCommond);
            logger.info("targetExecuteDeleteCommond:" + targetExecuteCommond);
        }
        mappingTask.setTargetMapping(mapping);
    }

}
